package com.example.demo.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.RandomUtil;
import com.cloopen.rest.sdk.BodyType;
import com.cloopen.rest.sdk.CCPRestSmsSDK;
import com.example.demo.exception.BusinessException;
import com.example.demo.mapper.SmsCodeMapper;
import com.example.demo.mapper.UserLogMapper;
import com.example.demo.pojo.*;
import com.example.demo.service.UserLogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

/**
 * @author admin
 */
@Service
public class UserLogServiceImpl implements UserLogService {
    @Autowired
    private UserLogMapper userMapper;

    @Autowired
    private SmsCodeMapper smsCodeMapper;

    // 验证码有效期5分钟
    private static final int EXPIRE_MINUTES = 1;

    private final BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();

    @Transactional
    @Override
    public UserLog register(String username, String password, String email,String phone) {
        if (userMapper.existsByUsername(username) > 0) {
            throw new BusinessException(500,"用户名已存在");
        }
        if (userMapper.existsByEmail(email) > 0) {
            throw new RuntimeException("邮箱已存在");
        }
        if (userMapper.existsByPhone(phone) > 0){
            throw new BusinessException(500,"手机号系统已存在");
        }
        UserLog user = new UserLog();
        user.setUsername(username);
        user.setPassword(passwordEncoder.encode(password));
        user.setEmail(email);
        user.setPhone(phone);
        userMapper.insertUser(user);
        return user;
    }

    @Override
    public UserLog login(String username, String password) {
        UserLog user = userMapper.findByUsername(username);
        if (user == null) {
            throw new BusinessException(500,"用户不存在");
        }
        if (!passwordEncoder.matches(password, user.getPassword())) {
           throw new BusinessException(500,"密码不正确");
        }
        return user;
    }

    @Override
    public int update(RegisterRequest request) {
        UserLog byUsername = userMapper.findByUsername(request.getUsername());
        if (byUsername == null) {
            throw new BusinessException(200,"用户不存在");
        }
        //先校验旧密码
        if (!passwordEncoder.matches(request.getOldPassword(), byUsername.getPassword())) {
            throw new BusinessException(200,"旧密码不对，请重新输入");
        }
        UserLog user = new UserLog().setId(byUsername.getId()).setUsername(request.getUsername()).setPassword(passwordEncoder.encode(request.getPassword())).setEmail(request.getEmail()).setUpdatedAt(DateUtil.toLocalDateTime(DateUtil.date()));
        int num = userMapper.updateUser(user);
        return num;
    }

    @Transactional
    @Override
    public int loginByPhone(LoginRequest request) {
        //手机验证码登录
        Map<String, Object> map = new HashMap<>();
        map.put("username", request.getUsername());
        UserLog user = userMapper.findByMap(map);
        if (user == null || (!request.getPhoneNum().equals(user.getPhone()))) {
            throw new BusinessException(500,"当前用户系统不存在");
        }
        int num = phoneCheck(user);
        return num;
    }

    /**
     * 验证码登录校验
     * @param request
     * @return
     */
    @Override
    public UserLog checkCode(LoginRequest request) {
// 查询最新的验证码记录
        SmsCode smsCode = smsCodeMapper.findLatestByPhone(request.getPhoneNum());
        if (smsCode == null) {
            throw new BusinessException(500,"验证码有误");
//            return false; // 没有验证码记录
        }

        // 检查是否过期
        LocalDateTime now = LocalDateTime.now();
        long minutesElapsed = ChronoUnit.MINUTES.between(smsCode.getCreateTime(), now);
        if (minutesElapsed > EXPIRE_MINUTES) {
            throw new BusinessException(500,"验证码已过期");
//            return false; // 验证码已过期
        }

        // 校验验证码是否一致
        boolean equals = smsCode.getCode().equals(request.getCode());
        if (!equals){
            //验证码无误
            throw new BusinessException(500,"验证码有误");
        }
        Map<String,Object> map = new HashMap<>();
        map.put("username", request.getUsername());
        map.put("phone", request.getPhoneNum());
        UserLog byMap = userMapper.findByMap(map);
        return byMap;
    }

    /***
     * 手机验证号登录
     * @param user
     * @return
     */
    @Transactional
    public int phoneCheck(UserLog user) {
        String serverIp = "app.cloopen.com";
        //请求端口
        String serverPort = "8883";
        //主账号,登陆云通讯网站后,可在控制台首页看到开发者主账号ACCOUNT SID和主账号令牌AUTH TOKEN
        String accountSId = "2c94811c946f6bfb0195d698b8d03ada";
        String accountToken = "cbe4e8accbbb499c9e31c57efc59c162";
        String appId = "2c94811c946f6bfb0195d698ba803ae1";
        CCPRestSmsSDK sdk = new CCPRestSmsSDK();
        sdk.init(serverIp,serverPort);
        sdk.setAccount(accountSId,accountToken);
        sdk.setAppId(appId);
        sdk.setBodyType(BodyType.Type_JSON);
        String to = user.getPhone();
        String templateId = "1";
        int code = RandomUtil.randomInt(1000,9999);
        String[] datas = {String.valueOf(code),"1"};
        String subAppend = "1234";
        String reqId = UUID.randomUUID().toString();
        //发送前将验证码存入本地数据库
        SmsCode smsCode = new SmsCode();
        smsCode.setPhone(user.getPhone());
        smsCode.setCode(Integer.valueOf(code).toString());
        smsCode.setCreateTime(LocalDateTime.now());
        smsCodeMapper.insert(smsCode);
        HashMap<String, Object> result = sdk.sendTemplateSMS(to, templateId, datas, subAppend, reqId);
        if("000000".equals(result.get("statusCode"))){
            HashMap<String,Object> data = (HashMap<String,Object>)result.get("data");
            Set<String> strings = data.keySet();
            for (String string : strings) {
                Object object = data.get(string);
                System.out.println(string + " = " + object);
                System.out.println("手机号:" + to + ", 验证码: " + code);
            }
        }else {
            throw new RuntimeException("错误码=" + result.get("statusCode") + "错误信息= " + result.get("statusMsg"));
        }
        return 1;
    }
}
